require "std"
require "loveplus"
require "vector"

require "view"
require "model"
require "light"
require "render"
require "physics"
require "ui"

require "d4"
require "d6"
require "d8"
require "d10"
require "d12"
require "d20"


--the board
do
  board={position=Vector{0,0,0}, surfaces={}}
  local black=true
  for x=-8.5, 7.5 do 
    for y=-8.5, 7.5 do
      local surface={ 
        center=Vector{x+0.5,y+0.5,0},
        normal=Vector{0,0,-1},
        color=black and 0x505050 or 0xd0d0d0,
        polygon={Vector{x,y,0},Vector{x+1,y,0},Vector{x+1,y+1,0},Vector{x,y+1,0}},
        object=board
      }
      black=not black
      table.insert(board.surfaces,surface)
    end
  end
end

objects={ }


function love.run() 
  
  local width,height=love.graphics.getResolution()
  view.transform(width/2,height/2,width/5)

--  local smallFont=love.graphics.newFont(width/50)
  local largeFont=love.graphics.newFont(width/40)
  love.graphics.setFont(largeFont)
  
  local helpTimeout=0
  
  while (love.im.tick()) do 
  
    

    -- do the physics
    physics.update(objects, math.max(love.timer.getDelta(),0.1))
    light.update(love.timer.getDelta())
    

    -- rendering the board
    for i,surface in ipairs(board.surfaces) do renderSurface(surface) end
    
    -- rendering the dice shadows
    for i,object in ipairs(objects) do 
      renderShadow(object)
    end
    
    -- z buffered rendering of the dice and the light
    local zorder, zscores={},{}
    for i,object in ipairs(objects) do for i,surface in ipairs(object.surfaces) do
      local x,y,z=view.project(surface.center+surface.object.position)
      table.insert(zorder,surface)
      zscores[surface]=-z
    end end
    
    table.insert(zorder,light)
    zscores[light]=-select(3,view.project(light.position))
    
    table.sort(zorder,function(a,b) return zscores[a]>zscores[b] end)
    for i,surface in ipairs(zorder) do 
      if surface==light then
        local x,y,z,p=view.project(light.position)
        love.graphics.setColor(0xFFFFFF)
        love.graphics.setPointSize(10+p*10)
        love.graphics.point(x,y)
      else
        renderSurface(surface) 
      end
    end

    --ui
    helpTimeout = helpTimeout + love.timer.getDelta()
    love.graphics.setColor(255,255,255)

    local offset=1/20
    local step=height/15
    local create,side

    if helpTimeout<10 then 
      love.graphics.setColor(200,200,200)
      love.graphics.printf("dice3 by Way\n\nleft click on a label rolls new dice\nright click on a label rolls but keeps old dice\nleft click on dice rolls them\nright click and drag rotates view"
      ,width*offset*4, step/3, width-width*offset*4,"left")
    end

    
    if button("d4", width*offset,2*step) then create,side=d4,"left" end
    if button("d6", width*offset,3*step) then create,side=d6,"left" end
    if button("d8", width*offset,4*step) then create,side=d8,"left" end
    if button("d10", width*offset,5*step) then create,side=d10,"left" end
    
    if button("d12", width*(1-offset),2*step) then create,side=d12,"right" end
    if button("d20", width*(1-offset),3*step) then create,side=d20,"right" end
    if button("d100", width*(1-offset),4*step) then create,side=function() return d10(), d100() end,"right" end
    if button("3d6", width*(1-offset),5*step) then create,side=function() return d6(),d6(), d6() end,"right" end
    
    --rolling some new dice
    if create then
      
      if love.im.mousePressed=='l' then objects={} end --remove every other dice if not a rightclick

      --start position of the dice
      local eye=view.eye()
      eye[3]=0
      if vector.abs(eye)>0.1 then eye=vector.unit(eye) else eye=Vector{1,0,0} end
      local sideVector=vector.cross(eye,{0,0,1})
      if side=="left" then sideVector=-sideVector end

      for i,object in ipairs {create()} do
        randomOrientation(object)
        object.position=(sideVector-eye)*6
        object.position[3]=2+2*i
        object.velocity=-object.position
        object.velocity[3]=2
        object.angularVelocity=vector.cross({0,0,1},object.velocity)

        object.color=math.random(0xFFFFFF)
        if object.color>0xC00000 and object.color%0x10000>0xC000 and object.color%0x100>0xC0 then object.textureColor=0 end

        table.insert(objects,object)
        light.target=object
        
      end
    else --no button, something else
      local object=ui.objectUnderMouse(objects)
      light.target=object --this will make the light follow the object

      if object and love.im.mousePressed=="l" then
        local impulse={view.eye()[1],view.eye()[2],10}
        if vector.abs(impulse)<0.01 then impulse={1,0,0} end
        physics.push(object,-20*vector.unit(impulse), Vector{math.random()-0.5,math.random()-0.5,1}) --roll!
      end

      if love.mouse.isDown('r') then
        view.raise((love.im.mouseDY or 0)/100)
        view.turn((love.im.mouseDX or 0)/100)
      end

      if love.im.mousePressed=='wd' then view.move(1.1) end
      if love.im.mousePressed=='wu' then view.move(0.9) end
    
    end
    
  end -- of loop
  
end


